package coins;

//~--- non-JDK imports --------------------------------------------------------

import coins.Engine.OrderStatus;

import com.dukascopy.api.IEngine;
import com.dukascopy.api.IEngine.OrderCommand;
import com.dukascopy.api.IOrder;
import com.dukascopy.api.IOrder.State;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.JFException;

//~--- JDK imports ------------------------------------------------------------

import java.text.SimpleDateFormat;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class Engine implements IEngine {
    List<IOrder>        openedOrders = new ArrayList<IOrder>();
    List<IOrder>        closedOrders = new ArrayList<IOrder>();
    private OrderStatus orderStatus;
    TesterClient        testerClient;

    enum OrderStatus { OPEN, CLOSE, NONE }

    public Engine(TesterClient client) {
        testerClient = client;
    }

    @Override
    public void closeOrders(IOrder... orders) throws JFException {
        for (IOrder order : orders) {
            order.close();
            openedOrders.remove(order);
            closedOrders.add(order);
            orderStatus = OrderStatus.CLOSE;
            ((Order) order).setCloseTime(testerClient.getTick().getTime());
        }
    }

    @Override
    public String getAccount() {
        throw new RuntimeException("Not implemented");
    }

    @Override
    public IOrder getOrder(String label) throws JFException {
        throw new RuntimeException("Not implemented");
    }

    @Override
    public IOrder getOrderById(String orderId) {
        throw new RuntimeException("Not implemented");
    }

    @Override
    public List<IOrder> getOrders() throws JFException {
        return new ArrayList<IOrder>(openedOrders);
    }

    @Override
    public List<IOrder> getOrders(Instrument instrument) throws JFException {
        return new ArrayList<IOrder>(openedOrders);
    }

    @Override
    public Type getType() {
        throw new RuntimeException("Not implemented");
    }

    @Override
    public void mergeOrders(IOrder... orders) throws JFException {
        throw new RuntimeException("Not implemented");
    }

    @Override
    public IOrder mergeOrders(String label, IOrder... orders) throws JFException {
        throw new RuntimeException("Not implemented");
    }

    @Override
    public IOrder submitOrder(String label, Instrument instrument, OrderCommand orderCommand, double amount)
            throws JFException {

        // Check if the order amount is within the set leevrage.
        int maxLeverage = testerClient.getLeverage();

        // Calculate the leverage of the current amount.
        double conversionFactor = testerClient.getTick().getAsk();
        double currentLeverage  = amount * 1000000 * conversionFactor / testerClient.getCurrentDeposit();

        if ((int) currentLeverage > maxLeverage) {
            System.out.println("Order amount is higher than max leverage ");

            return null;
        }

        // Close the previous order if any
        for (IOrder order : getOrders()) {
            closeOrders(order);
        }

        Order order = new Order(instrument, orderCommand, amount, label, State.FILLED);

        order.setCreationTime(testerClient.getTick().getTime());
        openedOrders.add(order);
        orderStatus = OrderStatus.OPEN;

        return order;
    }

    @Override
    public IOrder submitOrder(String label, Instrument instrument, OrderCommand orderCommand, double amount,
                              double price)
            throws JFException {
        throw new RuntimeException("Not implemented");
    }

    @Override
    public IOrder submitOrder(String label, Instrument instrument, OrderCommand orderCommand, double amount,
                              double price, double slippage)
            throws JFException {
        throw new RuntimeException("Not implemented");
    }

    @Override
    public IOrder submitOrder(String label, Instrument instrument, OrderCommand orderCommand, double amount,
                              double price, double slippage, double stopLossPrice, double takeProfitPrice)
            throws JFException {
        throw new RuntimeException("Not implemented");
    }

    @Override
    public IOrder submitOrder(String label, Instrument instrument, OrderCommand orderCommand, double amount,
                              double price, double slippage, double stopLossPrice, double takeProfitPrice,
                              long goodTillTime)
            throws JFException {
        throw new RuntimeException("Not implemented");
    }

    @Override
    public IOrder submitOrder(String label, Instrument instrument, OrderCommand orderCommand, double amount,
                              double price, double slippage, double stopLossPrice, double takeProfitPrice,
                              long goodTillTime, String comment)
            throws JFException {
        throw new RuntimeException("Not implemented");
    }

    public List<IOrder> getAllOrders() {
        List<IOrder> orders = new ArrayList<IOrder>(closedOrders);

        orders.addAll(openedOrders);

        return orders;
    }

    public void update(Tick tick) {

        // TODO Auto-generated method stub
        if (orderStatus == OrderStatus.OPEN) {
            ((Order) getAllOrders().get(getAllOrders().size() - 1)).setOpenTick(testerClient.getTick());
            orderStatus = OrderStatus.NONE;
        } else if (orderStatus == OrderStatus.CLOSE) {
            Order order = (Order) getAllOrders().get(getAllOrders().size() - 1);

            order.setCloseTick(testerClient.getTick());
            orderStatus = OrderStatus.NONE;

            // Also update the equity balance.
            double accountDepositBeforeTrade = testerClient.getCurrentDeposit();

            testerClient.updateCurrentDeposit(order.getProfitLossInUSD());
            testerClient.getAccount().calculateDrawdown();
            System.out.println(order.getAmount() + "," + order.getOrderCommand() + "," + order.getOpenPrice() + ","
                               + order.getClosePrice() + "," + order.getProfitLossInUSD() + ","
                               + order.getProfitLossInPips() + "," + (new Date(order.getCreationTime())).toGMTString()
                               + "," + (new Date(order.getCloseTime())).toGMTString() + "," + order.getFillTime() + ","
                               + order.getCloseTime() + "," + testerClient.getAccount().getEquity());
        }
    }
}


//~ Formatted by Jindent --- http://www.jindent.com
